# -*- coding: utf-8 -*-
"""
Chapter 3: Templates and Static Files

This demo covers:
- Template rendering with Jinja2
- Template inheritance
- Control structures (if, for)
- Template filters and custom filters
- Macros for reusable components
- Context processors for global data
- Static file serving
- Flash messages
"""

import os
import random
from datetime import datetime
from pprint import pformat

from flask import Flask, render_template, request, redirect, url_for, flash

app = Flask(__name__, template_folder='templates', static_folder='static')
app.secret_key = os.getenv('SECRET_KEY', 'dev-secret-key')

# Sample data for our templates
user_data = {
    'username': 'alice',
    'email': 'alice@example.com',
    'bio': 'A developer who loves Flask and Python',
    'is_admin': True
}

movies_data = [
    {'name': 'The Shawshank Redemption', 'year': 1994, 'rating': 9.3, 'director': 'Frank Darabont'},
    {'name': 'The Godfather', 'year': 1972, 'rating': 9.2, 'director': 'Francis Ford Coppola'},
    {'name': 'The Dark Knight', 'year': 2008, 'rating': 9.0, 'director': 'Christopher Nolan'},
    {'name': 'Pulp Fiction', 'year': 1994, 'rating': 8.9, 'director': 'Quentin Tarantino'},
    {'name': 'Forrest Gump', 'year': 1994, 'rating': 8.8, 'director': 'Robert Zemeckis'},
    {'name': 'Inception', 'year': 2010, 'rating': 8.7, 'director': 'Christopher Nolan'},
    {'name': 'The Matrix', 'year': 1999, 'rating': 8.7, 'director': 'The Wachowskis'},
    {'name': 'Goodfellas', 'year': 1990, 'rating': 8.7, 'director': 'Martin Scorsese'},
    {'name': 'Se7en', 'year': 1995, 'rating': 8.6, 'director': 'David Fincher'},
    {'name': 'The Silence of the Lambs', 'year': 1991, 'rating': 8.6, 'director': 'Jonathan Demme'}
]


# Custom template filters
@app.template_filter('reverse')
def reverse_filter(s):
    """Reverse a string."""
    return s[::-1]


@app.template_filter('shuffle')
def shuffle_filter(lst):
    """Shuffle a list."""
    result = list(lst)
    random.shuffle(result)
    return result


@app.template_filter('currency')
def currency_filter(amount):
    """Format a number as currency."""
    return f"${amount:,.2f}"


# Custom template tests
@app.template_test('more_than_100')
def is_more_than_100(n):
    """Check if a number is more than 100."""
    return n > 100 == 0


@app.template_test('empty')
def is_empty(value):
    """Check if a value is empty."""
    if value is None:
        return True
    try:
        return len(value) == 0
    except TypeError:
        return not value


# Custom global functions
@app.template_global()
def get_random_number():
    """Generate a random number."""
    return random.randint(1, 100)


@app.template_global()
def format_price(amount):
    """Format a price."""
    return f"${amount:.2f}"


@app.template_global()
def pprint(value):
    """Pretty-print values inside templates."""
    return pformat(value, indent=2, width=80, compact=False)


# Context processors - add global variables to all templates
@app.context_processor
def inject_global_vars():
    """Add global variables to all templates."""
    return {
        'site_name': 'Flask Templates Demo',
        'current_year': datetime.now().year
    }


@app.context_processor
def inject_navigation():
    """Add navigation data to all templates."""
    nav_items = [
        {'name': 'Home', 'url': url_for('index')},
        {'name': 'Watchlist', 'url': url_for('watchlist')},
        {'name': 'Watchlist Pro', 'url': url_for('watchlist_pro')},
        {'name': 'Movies', 'url': url_for('movie_list')},
        {'name': 'Controls', 'url': url_for('control_structures')},
        {'name': 'Filters/Macros', 'url': url_for('filters_macros')},
        {'name': 'Simple Macros', 'url': url_for('simple_macros')},
        {'name': 'Context', 'url': url_for('context_processors')},
        {'name': 'Flash', 'url': url_for('flash_demo')}
    ]
    return {'navigation': nav_items}


# Template global function
@app.template_global()
def get_current_time():
    """Get current time as a formatted string."""
    return datetime.now().strftime("%Y-%m-%d %H:%M:%S")


# Routes
@app.route('/')
def index():
    """Home page."""
    return render_template('index.html', user=user_data, movies=movies_data)


@app.route('/watchlist')
def watchlist():
    """Display a simple watchlist."""
    return render_template('watchlist.html', user=user_data, movies=movies_data)


@app.route('/watchlist-pro')
def watchlist_pro():
    """Display a watchlist with static files."""
    return render_template('watchlist_with_static.html', user=user_data, movies=movies_data)


@app.route('/movies')
def movie_list():
    """Display movie list."""
    return render_template('movie_list.html', user=user_data, movies=movies_data)


@app.route('/controls')
def control_structures():
    """Demonstrate control structures."""
    return render_template('control_structures.html', user=user_data, movies=movies_data)


@app.route('/filters-macros')
def filters_macros():
    """Demonstrate filters and macros."""
    return render_template('filters_macros.html', user=user_data, movies=movies_data)


@app.route('/simple-macros')
def simple_macros():
    """Demonstrate simple macros."""
    return render_template('simple_macros.html', user=user_data, movies=movies_data)


@app.route('/context')
def context_processors():
    """Demonstrate context processors."""
    return render_template('context_processors.html', user=user_data, movies=movies_data)


@app.route('/flash', methods=['GET', 'POST'])
def flash_demo():
    """Demonstrate flash messages."""
    if request.method == 'POST':
        message = request.form.get('message', 'Default message')
        category = request.form.get('category', 'info')
        flash(message, category)  # demos/ch3_templates/templates/base.html:48
        return redirect(url_for('flash_demo'))

    # Handle quick action buttons
    action = request.args.get('action')
    if action:
        if action == 'success':
            flash('Operation completed successfully!', 'success')
        elif action == 'error':
            flash('An error occurred while processing your request.', 'error')
        elif action == 'warning':
            flash('This is a warning message.', 'warning')
        return redirect(url_for('flash_demo'))

    return render_template('flash_demo.html', user=user_data, movies=movies_data)


# Error handlers
@app.errorhandler(404)
def not_found(error):
    """Handle 404 errors."""
    return render_template('errors/404.html', user=user_data, movies=movies_data), 404


@app.errorhandler(500)
def internal_error(error):
    """Handle 500 errors."""
    return render_template('errors/500.html', user=user_data, movies=movies_data), 500


if __name__ == '__main__':
    app.run(
        host=os.getenv('FLASK_HOST', '127.0.0.1'),
        port=int(os.getenv('FLASK_PORT', 5000)),
        debug=os.getenv('FLASK_DEBUG', 'True').lower() == 'true'
    )
